内部定时计数器
硬件构成的定时/计数器在工作时不占用CPU 时间的优点,
除非定时器/计数器溢出,才能中断 CPU 的当前操作
比使用循环程序产生延时要优越得多,可以提高 CPU 的效率
时钟系统
XTAL1
和 XTAL2
之间跨接晶体振荡器和微调电容,
从而构成一个稳定的自激振荡器
MCS-51 振荡频率 6MHZ 或 12MHZ
机器周期:
完成一个基本操作所需的时间,包含 12 个振荡周期
1 us 微秒
8051 定时器结构
- TH0 TL0 TH1 TL1
- TCON
- TMOD
T1 T0 定时器/计数器
十六位定时/计数器
由两个8位特殊功能寄存器构成
十六位计数器=高八位 (TH)+低八位 (TL) 计数器
Time High/Low TH/TL
定时器 0 T0
: TH0
+ TL0
定时器 1 T1
: TH1
+ TL1
TCON 控制器寄存器
TCON
控制器寄存器 88H
除可字节寻址外,各位还可位寻址
低四位用于 外部中断
8FH | 8EH | 8DH | 8CH | 8BH | 8AH | 89H | 88H |
---|---|---|---|---|---|---|---|
TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | TE0 | IT0 |
T1 溢出标志 | T1 运行控制 | T0 溢出标志 | T0 运行控制 |
运行控制 TR
:软件上的启动
置 1,来启动定时器
SETB TR1/TR0
启动定时器
置 0,来关闭定时器
溢出标志 TF
:硬件上的标志位
定时器溢出时,硬件自动使得中断触发器置 1,并由 CPU 申请中断
CPU 响应中断进入中断服务程序后,会被硬件自动清 0, 也可软件清 0
如果进入到中断服务程序中,TF
会自动清零
但是如果只是查询方式溢出,未进入到中断服务程序中,要软件手动清零
TMOD 工作模式寄存器
TMOD
工作模式寄存器 89H
不可位寻址,只能用字节设置定时器的工作模式
- 低半字节设置T0
- 高半字节设置T1
GATE | M1 | M0 | GATE | M1 | M0 | ||
---|---|---|---|---|---|---|---|
T1选通控制 | T1功能选择 | T1工作模式选择 | T1工作模式选择 | T0选通控制 | T0功能选择 | T0工作模式选择 | T0工作模式选择 |
GATE 选通控制
0:不受
使计数器的 TR0
或 TR1
置 1就可启动对应的计数器 T0 或 T1
1:受
先要硬件上的
才能通过 TR0 或 TR1 置 1 启动对应的计数器
功能选择
0:定时方式
定时器计数 8051 片内脉冲,即对机器周期计数
1:计数方式
计数器的输入来自T0(P3.4)或T1(P3.5)端的外部脉冲
M1 M0 工作模式选择
00:模式 0 13 位计数器
0 1:模式 1 16 位计数器
1 0:模式 2 自动再装入 8 位计数器,自动重装载
1 1:模式 3 T0 分成两个 8 位计数器,T1 停止计数
模式 1
16 位计数器
在这种模式下,16位寄存器(TH0和TL0)用于装载计数/定时的初值。启动定时器后,
当TL0的低8位溢出时,向TH0进位;
TH0溢出时,向中断标志TF0进位(硬件置位TF0),并申请中断
定时时间:
定时的时间 设置定时器的初值 振荡周期 为晶振频率 - 12 表示一个基本操作占 12 个振荡周期
实际的例子
设T0工作模式1,定时时间为1ms,fosc=12MH
编程实现其定时功能。定时时间到,P1.0取反
-
T0 工作模式 1
TMOD : 0000 0001
MOV TMOD,#01H
-
定时时间为 1ms =1000×1us
fosc=12MH --> 机器周期 1us
1ms =1000×1us 也即要计数 1000 次
设置 T0 计数器初值:
1111 1110 0001 1000 (二进制) FC 18(十六进制)
高八位 TH0:MOV TH0,#0FCH
低八位 TL0:MOV TL0,#18H
-
启动 T0 定时器
TCON 可位寻址
SETB TR0
查询方式
MOV TMOD,#01H ;定时器0 模式1
MOV TL0,#18H
MOV TH0,#0FCH ;送初值
STEB TR0 ;启动定时器
LOOP:JBC TF0,NEXT
SJMP LOOP
NEXT:MOV TL0,#18H
MOV TH0,#0FCH ;重新赋初值
CPL P1.0
SJMP LOOP
#include<reg51.h>
sbit P1_0=P1^0;
void main(void)
{
TMOD=0x01;
TH0=0xFC;
TL0=0x18;
TR0=1;
while(1)
{
do{}
while(!TF0);
P1_0=!P1_0;
TH0=0xFC;
TL0=0x18;
TF0=0; //溢出标志位清零
}
}
中断方式
8051中断系统
定时器中断标志位作为中断信号
标志位表征“重要的”事情发生了
CPU 来判断电信号的高低电平,作出响应
ORG 000H
RESET: AJMP MAIN
ORG 000BH
AJMP ISR0
ORG 0030H
MAIN: MOV TMOD,#01H
MOV TL0,#18H
MOV TH0,#0FCH
SETB EA
SETB ET0
SETB TR0
HERE: SJMP HEAR
ISR0: MOV TL0,#18H
MOV TH0,#0FCH
CPL P1.0
RETI
#include<reg51.h>
sbit P1_0=P1^0;
void time0(void) interrput 1
{
TH0=0xFC; //重新赋初值
TL0=0x18;
P1_0=!P1_0;
}
void main(void)
{
TMOD=0x01;
TH0=0xFC;
TL0=0x18;
EA=1; //中断总允许
ET0=1; //T0溢出允许
TR0=1; //启动定时器0
while(1)
{}
}
模式二
该模式把TL0(TL1)配置成一个可以自动重装载的8位定时器/计数器
定时器 1 模式二用于8051串口通信中的串行口波特率发生器
以 T0 定时器为例:
TL0 用作 8 位计数器 0~255
TH0 保存初值
TL0计数溢出时,
- 不仅使溢出中断标志位TF0置1
- 而且还自动把TH0中的内容重新装载到TL0中
计数次数:
计数时间:
TMOD
0110 0000 T1 计时器模式二
计数 100 次
256-100=156 -->1001 1100 --> 9CH
数码管
静态显示
1.设计定时器,每隔1秒的时间,计时器自动加1,计时器个位满十向高位进位,累计计时99秒即清0重新计数。
2.计数过程中,能够分别实现计时器清零、暂停功能。(需增加开关电路)
3.清零或暂停功能选择其中一项功能通过中断方式设计实现。
unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} //声明table数组
#include<reg51.h>
sbit P1_0 = P1^0;
unsigned char counter=1000;
unsigned char
table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}
unsigned char i= 0 ;unsigned char j=0;
void main(void)
{
TMOD=0x01;
P2=table[0];
P1=table[0];
TH0=0xFC;
TL0=0x18;
EA=1;
ET0=1;EX0=1;EX1=1;
TR=0;
while(1)
{}
}
void ISR0(void) interrupt 0
{
TH0=0xFC;
TL0=0x18;
counter--;
if(counter==0)
{
counter=1000;
i++;
if(i==10)
{
i=0;
j++;
if(j==10)
{
j=0;
}
}
P1=table[i];
P2=table[j];
}
}
void ext_int0(void) interrupt 0
{
P2=table[0];
P1=table[0];
i=0; j=0; //外部中断0,清零
}
void ext_int1(void) interrupt 2
{
TR0=!TR0; //外部中断1,暂停
}
动态扫描
为了简化硬件电路,通常将所有位的段选线相应并联在一起,由一个8位I/O控制,形成段选线多路复用。而各位的共阳极或共阴极分别由相应的I/O线控制,实现各位的分时选通
在某一时刻,只让某一位位选线处于选通状态,而其他各位的位选线处于关闭状态,同时,段选线上输出相应位要显示的字符的字型码